/**
 * This file was created by Taylor Garren for use in SpaceTrader
 */

import java.io.Serializable;

/**
 * The Marketplace is where the resources are bought and sold. It is able to
 * handle the associated methods to allow for transactions.
 * 
 * @author Taylor Garren
 * @version 1.0
 */

public class Marketplace implements Serializable {
    
    /**
     * The planet that the player is currently on
     */
    
    private final Planet planet;
    
    /**
     * The user
     */
    
    private final Player player;
    
    /**
     * The resources held by this particular planet
     */
    
    private final Resource[] resources;
    
    /**
     * The prices of the resources
     */
    
    private final double[] priceArray;
    
    /**
     * The ship's cargo
     */
    
    private final Resource[] cargo;
    
    /**
     * The player's ship
     */
    
    private final Ship ship;

    /**
     * Creates a new Marketplace
     * 
     * @param planet
     *            The planet on which this Marketplace will be placed.
     * @param player
     *            The player reference to be used for buying and selling.
     */

    public Marketplace(Planet planet, Player player) {
	this.planet = planet;
	this.player = player;
	this.ship = player.getShip();
	cargo = ship.getCargo();
	resources = planet.getItemsForSale();
	priceArray = createPriceArray();
    }

    /**
     * Checks that the user has the money to buy the resource and that the
     * requested number of resources is available for sale.
     * 
     * @param resourceIndex The index at the resource the user wishes to buy
     * in the given resource array
     * @param numItems The amount of the resource the user wishes to buy
     * @return True if the resource can be bought, false otherwise.
     */
    public boolean canBuy(int resourceIndex, int numItems) {
	if (numItems < 0) {
	    return false;
	}
	if (resourceIndex > resources.length || resourceIndex < 0) {
	    throw new IndexOutOfBoundsException();
	}
	if (player.getWallet() - numItems * priceArray[resourceIndex] < 0) {
	    return false;
	}
	if (resources[resourceIndex].getMultiplicity() < numItems) {
	    return false;
	}
	if ((player.getShip().getTotalCargo() + numItems) > player.getShip()
		.getThisCapacity()) {
	    return false;
	}
	return true;
    }

    /**
     * Checks if a given resource can be sold to the marketplace.
     * 
     * @param resourceIndex
     *            The internal index representation of the resource.
     * @param numItems
     *            How many items are to be sold.
     * @return True if the items can be sold, false otherwise.
     */
    public boolean canSell(int resourceIndex, int numItems) {
	if (numItems < 0 || resourceIndex > resources.length) {
	    return false;
	}
	if (resourceIndex < 0) {
	    throw new IndexOutOfBoundsException();
	}
	if (numItems > cargo[resourceIndex].getMultiplicity()) {
	    return false;
	}
	return true;
    }

    /**
     * Used to get the array of all the resources that this marketplace sells.
     * 
     * @return An array of the resources that are sold by this marketplace.
     */
    public Resource[] getResources() {
	return resources;
    }

    /**
     * Used to purchase a given resource and to transfer it to the player.
     * 
     * @param resourceIndex
     *            The internal index representation of the resource.
     * @param numItems
     *            The quantity of the resource that is to be bought.
     */
    public void buy(int resourceIndex, int numItems) {
	if (canBuy(resourceIndex, numItems)) {
	    player.setWallet(player.getWallet() - numItems
		    * priceArray[resourceIndex]);
	    cargo[resourceIndex].setMultiplicity(cargo[resourceIndex]
		    .getMultiplicity() + numItems);
	    resources[resourceIndex].setMultiplicity(resources[resourceIndex]
		    .getMultiplicity() - numItems);
	    player.getShip().setTotalCargo(
		    player.getShip().getTotalCargo() + numItems);
	}

    }

    /**
     * Used to sell a given resource and to transfer it to the Marketplace.
     * 
     * @param resourceIndex
     *            The internal representation of the resource.
     * @param numItems
     *            The quantity of the resource that is to be sold.
     */
    public void sell(int resourceIndex, int numItems) {
	if (canSell(resourceIndex, numItems)) {
	    player.setWallet(player.getWallet() + numItems
		    * priceArray[resourceIndex]);
	    cargo[resourceIndex].setMultiplicity(cargo[resourceIndex]
		    .getMultiplicity() - numItems);
	    resources[resourceIndex].setMultiplicity(resources[resourceIndex]
		    .getMultiplicity() + numItems);
	    player.getShip().setTotalCargo(
		    player.getShip().getTotalCargo() - numItems);
	}
    }

    /**
     * Builds the price array from the given resources
     * @return A price array
     */
    public final double[] createPriceArray() {
	final double[] priceArray = new double[resources.length];
	for (int i = 0; i < resources.length; i++) {
	    priceArray[i] = resources[i].getPrice();
	}
	return priceArray;
    }

    /**
     * @return The array of resource prices
     */
    public double[] getPriceArray() {
	return priceArray;
    }
    
    /**
     * @return The results of the default toString() method for a class
     */
    public String toString() {
	return this.toString();
    }

    /*
     * MTLP = Minimum Tech Level to Produce this resource (You can't buy on
     * planets below this level) MTLU = Minimum Tech Level to Use this resource
     * (You can't sell on planets below this level) TTP = Tech Level which
     * produces the most of this item IPL = Price increase per tech level Var =
     * variance is the maximum percentage that the price can vary above or below
     * the base IE = Radical price increase event, when this even happens on a
     * planet, the price may increase astronomically CR = When this condition is
     * present, the price of this resource is unusually low ER = When this
     * condition is present, the resource is expensive MTL = Min price offered
     * in space trade with random trader (not on a planet) MTH = Max price
     * offered in space trade with random trader (not on a planet)
     */
}
